package cn.coisini.model.common.log.service.impl;

import cn.coisini.mapper.AsyncLoginLogMapper;
import cn.coisini.model.common.dtos.Result;
import cn.coisini.model.common.enums.ResultEnum;
import cn.coisini.model.common.exception.CustomAuthenticationException;
import cn.coisini.model.common.log.service.AsyncLoginLogService;
import cn.coisini.model.pojo.AsyncLoginLog;
import cn.coisini.model.vo.AsyncLoginLogQueryVo;
import cn.coisini.utils.IdWorker;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.apache.commons.lang3.ObjectUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.Optional;

import static cn.coisini.model.common.constants.AdminConstants.USERNAME;

/**
 * @author xiangshaw
 * Description: 系统访问记录 服务实现类
 */
@Service
public class AsyncLoginLogServiceImpl extends ServiceImpl<AsyncLoginLogMapper, AsyncLoginLog> implements AsyncLoginLogService {

    /**
     * 保存登录日志
     */
    @Override
    public void recordLoginLog(AsyncLoginLog asyncLoginLog) {
        asyncLoginLog.setId(String.valueOf(new IdWorker().nextId()));
        asyncLoginLog.setUserId(asyncLoginLog.getUserId());
        asyncLoginLog.setUsername(asyncLoginLog.getUsername());
        asyncLoginLog.setLoginIp(asyncLoginLog.getLoginIp());
        asyncLoginLog.setLoginIpSource(asyncLoginLog.getLoginIpSource());
        asyncLoginLog.setLoginIpCity(asyncLoginLog.getLoginIpCity());
        asyncLoginLog.setMsg(asyncLoginLog.getMsg());
        asyncLoginLog.setStatus(asyncLoginLog.getStatus());
        baseMapper.insert(asyncLoginLog);
    }

    /**
     * 条件分页查询登录日志
     *
     * @param asyncLoginLogQueryVo 查询条件对象
     * @return 分页查询结果
     */
    @Override
    public Result<Page<AsyncLoginLog>> pagingQuery(AsyncLoginLogQueryVo asyncLoginLogQueryVo) {
        QueryWrapper<AsyncLoginLog> wrapper = getLoginLogQueryWrapper(asyncLoginLogQueryVo);
        // 分页条件（当前页、每页条数）
        Page<AsyncLoginLog> page = new Page<>(asyncLoginLogQueryVo.getCurrent(), asyncLoginLogQueryVo.getLimit());
        Page<AsyncLoginLog> loginLogPage = page(page, wrapper);
        return Result.ok(loginLogPage);
    }

    private static QueryWrapper<AsyncLoginLog> getLoginLogQueryWrapper(AsyncLoginLogQueryVo asyncLoginLogQueryVo) {
        // 获取条件值
        String username = asyncLoginLogQueryVo.getUsername();
        String createTimeBegin = asyncLoginLogQueryVo.getCreateTimeBegin();
        String createTimeEnd = asyncLoginLogQueryVo.getCreateTimeEnd();
        // 封装条件
        QueryWrapper<AsyncLoginLog> wrapper = new QueryWrapper<>();
        // 根据 登录用户名称、大于等于开始时间、小于等于创建时间
        if (!ObjectUtils.isEmpty(username)) {
            wrapper.like(USERNAME, username);
        } // 大于等于开始时间
        if (!ObjectUtils.isEmpty(createTimeBegin)) {
            wrapper.ge("create_time", createTimeBegin);
        } // 小于等于结束时间
        if (!ObjectUtils.isEmpty(createTimeBegin)) {
            wrapper.le("create_time", createTimeEnd);
        } //排序
        wrapper.eq("del_flag", 0).orderByDesc("id");
        return wrapper;
    }

    /**
     * 根据ID查询登录日志
     *
     * @param id 日志ID
     * @return 查询结果 asyncLoginLog != null ? Result.ok(asyncLoginLog) : Result.error(ResultEnum.DATA_NOT_EXIST);
     */
    @Override
    public Result<AsyncLoginLog> get(String id) {
        return Optional.ofNullable(id)
                .map(this::getById)
                .map(Result::ok)
                .orElseGet(() -> Result.error(ResultEnum.PARAM_ERROR));
    }

    /**
     * 根据ID删除登录日志
     *
     * @param id 日志ID
     * @return 删除结果
     */
    @Transactional
    @Override
    public Result<ResultEnum> removeLoginLogById(String id) {
        return Optional.ofNullable(id)
                .map(this::getById)
                .map(loginLog -> {
                    boolean removed = removeById(loginLog.getId());
                    if (!removed) {
                        throw new CustomAuthenticationException(ResultEnum.LOG_DELETE_FAIL, ResultEnum.LOG_DELETE_FAIL.getMessage());
                    }
                    return Result.ok(ResultEnum.LOG_DELETE_SUCCESS);
                })
                .orElse(Result.error(ResultEnum.LOG_DELETE_FAIL));
    }

    /**
     * 批量删除登录日志
     *
     * @param ids 要删除的日志ID列表
     * @return 删除结果
     */
    @Transactional
    @Override
    public Result<ResultEnum> batchRemove(List<String> ids) {
        return Optional.ofNullable(ids)
                .map(idList -> {
                    if (idList.isEmpty()) {
                        throw new IllegalArgumentException("ID 列表不能为空");
                    }
                    List<AsyncLoginLog> loginLogs = listByIds(idList);
                    if (loginLogs.isEmpty()) {
                        throw new IllegalArgumentException("指定的登录日志不存在");
                    }
                    int i = baseMapper.deleteBatchIds(idList);
                    if (i != 0) {
                        return Result.ok(ResultEnum.SUCCESS);
                    }
                    throw new CustomAuthenticationException(ResultEnum.LOG_DELETE_FAIL, ResultEnum.LOG_DELETE_FAIL.getMessage());
                })
                .orElse(Result.error(ResultEnum.PARAM_ERROR.getCode(), "ID 列表不能为空"));

    }

    /**
     * 根据用户ID查询最后登录日志
     * @param userId 用户ID
     * @return 用户IP属地
     */
    @Override
    public AsyncLoginLog getLastLoginLogByUserId(String userId) {
        // 构建查询条件，只获取指定用户的最后登录日志
        QueryWrapper<AsyncLoginLog> wrapper = new QueryWrapper<>();
        wrapper.eq("user_id", userId).orderByDesc("access_time").last("LIMIT 1");
        return getOne(wrapper);
    }

}
